/****************************************************************************

 Copyright (C) 2009 Jean Pierre Charalambos. All rights reserved.

 Dialog contributed by: Juan Carlos León (http://code.google.com/p/maku/).

 This file is part of maku version 0.2.

 http://code.google.com/p/maku/
 email: jpcharalambosh@unal.edu.co

 This file may be used under the terms of the GNU General Public License
 versions 2.0 or 3.0 as published by the Free Software Foundation and
 appearing in the COPYING file included in the packaging of this file.

 This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#include "shaderdialog.h"
#include <iostream>

ShaderDialog::ShaderDialog ( SceneBase *scene, QWidget *parent )
        : QDialog ( parent ) {
    setupUi ( this );
    parentScene=scene;

    uniforms=parentScene->getCurrentUniforms();


    //integer sliders
    connect ( sliderX, SIGNAL ( valueChanged ( int ) ),
              valueX, SLOT ( setValue ( int ) ) );
    connect ( valueX, SIGNAL ( valueChanged ( int ) ),
              sliderX, SLOT ( setValue ( int ) ) );
    connect ( maxValueX, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeXmaximum ( int ) ) );
    connect ( minValueX, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeXminimum ( int ) ) );

    connect ( sliderY, SIGNAL ( valueChanged ( int ) ),
              valueY, SLOT ( setValue ( int ) ) );
    connect ( valueY, SIGNAL ( valueChanged ( int ) ),
              sliderY, SLOT ( setValue ( int ) ) );
    connect ( maxValueY, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeYmaximum ( int ) ) );
    connect ( minValueY, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeYminimum ( int ) ) );

    connect ( sliderZ, SIGNAL ( valueChanged ( int ) ),
              valueZ, SLOT ( setValue ( int ) ) );
    connect ( valueZ, SIGNAL ( valueChanged ( int ) ),
              sliderZ, SLOT ( setValue ( int ) ) );
    connect ( maxValueZ, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeZmaximum ( int ) ) );
    connect ( minValueZ, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeZminimum ( int ) ) );

    connect ( sliderW, SIGNAL ( valueChanged ( int ) ),
              valueW, SLOT ( setValue ( int ) ) );
    connect ( valueW, SIGNAL ( valueChanged ( int ) ),
              sliderW, SLOT ( setValue ( int ) ) );
    connect ( maxValueW, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeWmaximum ( int ) ) );
    connect ( minValueW, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeWminimum ( int ) ) );

    //add shader names
    QVectorIterator<Uniform> iter ( uniforms );
    while ( iter.hasNext() ) {
        Uniform tempUni= ( iter.next() );
        shaderCombo->addItem ( tempUni.getName(),QVariant ( "" ) );
    }

    //double sliders
    connect ( doubleSliderX, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeDoubleComboXvalue ( int ) ) );
    connect ( doubleValueX, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleXSliderValue ( double ) ) );
    connect ( doubleMaxValueX, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleXmaximumValue ( double ) ) );
    connect ( doubleMinValueX, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleXminimumValue ( double ) ) );
    connect ( doubleValueX, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleXSliderValue ( double ) ) );
    connect ( doubleValueX, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( applyXvalueChange ( double ) ) );//actual change on the scene

    connect ( doubleSliderY, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeDoubleComboYvalue ( int ) ) );
    connect ( doubleValueY, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleYSliderValue ( double ) ) );
    connect ( doubleMaxValueY, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleYmaximumValue ( double ) ) );
    connect ( doubleMinValueY, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleYminimumValue ( double ) ) );
    connect ( doubleValueY, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( applyYvalueChange ( double ) ) );//actual change on the scene

    connect ( doubleSliderZ, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeDoubleComboZvalue ( int ) ) );
    connect ( doubleValueZ, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleZSliderValue ( double ) ) );
    connect ( doubleMaxValueZ, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleZmaximumValue ( double ) ) );
    connect ( doubleMinValueZ, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleZminimumValue ( double ) ) );
    connect ( doubleValueZ, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( applyZvalueChange ( double ) ) );//actual change on the scene

    connect ( doubleSliderW, SIGNAL ( valueChanged ( int ) ),
              this, SLOT ( changeDoubleComboWvalue ( int ) ) );
    connect ( doubleValueW, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleWSliderValue ( double ) ) );
    connect ( doubleMaxValueW, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleWmaximumValue ( double ) ) );
    connect ( doubleMinValueW, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( changeDoubleWminimumValue ( double ) ) );
    connect ( doubleValueW, SIGNAL ( valueChanged ( double ) ),
              this, SLOT ( applyWvalueChange ( double ) ) );//actual change on the scene

    connect ( shaderCombo, SIGNAL ( activated ( int ) ),
              this, SLOT ( selectShaderUniform ( int ) ) );

    if(uniforms.size()>0)
        selectShaderUniform ( 0 );
    else{
        doubleSliderX->setEnabled ( false );
        doubleMaxValueX->setEnabled ( false );
        doubleMinValueX->setEnabled ( false );
        doubleValueX->setEnabled ( false );
        doubleSliderY->setEnabled ( false );
        doubleMaxValueY->setEnabled ( false );
        doubleMinValueY->setEnabled ( false );
        doubleValueY->setEnabled ( false );
        doubleSliderZ->setEnabled ( false );
        doubleMaxValueZ->setEnabled ( false );
        doubleMinValueZ->setEnabled ( false );
        doubleValueZ->setEnabled ( false );
        doubleSliderW->setEnabled ( false );
        doubleMaxValueW->setEnabled ( false );
        doubleMinValueW->setEnabled ( false );
        doubleValueW->setEnabled ( false );
        buttonBox->setEnabled(false);
        shaderCombo->setEnabled(false);
    }

}

//
void ShaderDialog::applyXvalueChange ( double newValue ) {
    parentScene->applyXvalueChange ( newValue,currentUniform );
}
void ShaderDialog::applyYvalueChange ( double newValue ) {
    parentScene->applyYvalueChange ( newValue,currentUniform );
}
void ShaderDialog::applyZvalueChange ( double newValue ) {
    parentScene->applyZvalueChange ( newValue,currentUniform );
}
void ShaderDialog::applyWvalueChange ( double newValue ) {
    parentScene->applyWvalueChange ( newValue,currentUniform );
}

//combo
void ShaderDialog::selectShaderUniform ( int selectedIndex ) {

    currentUniform=uniforms.at ( selectedIndex );
    if ( currentUniform.getType() ==1 ) {
        stackedWidget->setCurrentIndex ( 0 );
    } else {//floats
        stackedWidget->setCurrentIndex ( 1 );

        doubleSliderX->blockSignals ( true );
        doubleValueX->setValue ( currentUniform.getValueAsFloat ( 1 ) );

        float range=3.0;
        if ( currentUniform.getValueAsFloat ( 1 ) *0.2>3 )
            range=currentUniform.getValueAsFloat ( 1 ) *0.2;
        doubleMaxValueX->setValue ( currentUniform.getValueAsFloat ( 1 ) + ( int ) range );
        doubleMinValueX->setValue ( currentUniform.getValueAsFloat ( 1 )- ( int ) range );

        doubleSliderX->setValue ( currentUniform.getValueAsFloat ( 1 ) *10 );
        doubleSliderX->blockSignals ( false );

        doubleSliderY->setEnabled ( false );
        doubleMaxValueY->setEnabled ( false );
        doubleMinValueY->setEnabled ( false );
        doubleValueY->setEnabled ( false );
        doubleSliderZ->setEnabled ( false );
        doubleMaxValueZ->setEnabled ( false );
        doubleMinValueZ->setEnabled ( false );
        doubleValueZ->setEnabled ( false );
        doubleSliderW->setEnabled ( false );
        doubleMaxValueW->setEnabled ( false );
        doubleMinValueW->setEnabled ( false );
        doubleValueW->setEnabled ( false );

        switch ( currentUniform.getSize() ) {
        case 4:
            doubleSliderW->setEnabled ( true );
            doubleMaxValueW->setEnabled ( true );
            doubleMinValueW->setEnabled ( true );
            doubleValueW->setEnabled ( true );

            doubleSliderW->blockSignals ( true );
            doubleValueW->setValue ( currentUniform.getValueAsFloat ( 4 ) );

            if ( currentUniform.getValueAsFloat ( 4 ) *0.2>3 )
                range=currentUniform.getValueAsFloat ( 4 ) *0.2;


            doubleMaxValueW->setValue ( currentUniform.getValueAsFloat ( 4 ) + ( int ) range );
            doubleMinValueW->setValue ( currentUniform.getValueAsFloat ( 4 )- ( int ) range );

            doubleSliderW->setValue ( currentUniform.getValueAsFloat ( 4 ) *10 );
            doubleSliderW->blockSignals ( false );
        case 3:
            doubleSliderZ->setEnabled ( true );
            doubleMaxValueZ->setEnabled ( true );
            doubleMinValueZ->setEnabled ( true );
            doubleValueZ->setEnabled ( true );

            doubleSliderZ->blockSignals ( true );
            doubleValueZ->setValue ( currentUniform.getValueAsFloat ( 3 ) );

            std::cout<<"Current Value for Z"<<currentUniform.getValueAsFloat ( 3 ) <<std::endl;
            if ( currentUniform.getValueAsFloat ( 3 ) *0.2>3 )
                range=currentUniform.getValueAsFloat ( 3 ) *0.2;
            doubleMaxValueZ->setValue ( currentUniform.getValueAsFloat ( 3 ) + ( int ) range );
            doubleMinValueZ->setValue ( currentUniform.getValueAsFloat ( 3 )- ( int ) range );

            doubleSliderZ->setValue ( currentUniform.getValueAsFloat ( 3 ) *10 );
            doubleSliderZ->blockSignals ( false );
        case 2:
            doubleSliderY->setEnabled ( true );
            doubleMaxValueY->setEnabled ( true );
            doubleMinValueY->setEnabled ( true );
            doubleValueY->setEnabled ( true );

            doubleSliderY->blockSignals ( true );
            doubleValueY->setValue ( currentUniform.getValueAsFloat ( 2 ) );

            if ( currentUniform.getValueAsFloat ( 2 ) *0.2>3 )
                range=currentUniform.getValueAsFloat ( 2 ) *0.2;
            doubleMaxValueY->setValue ( currentUniform.getValueAsFloat ( 2 ) + ( int ) range );
            doubleMinValueY->setValue ( currentUniform.getValueAsFloat ( 2 )- ( int ) range );

            doubleSliderY->setValue ( currentUniform.getValueAsFloat ( 2 ) *10 );
            doubleSliderY->blockSignals ( false );
            break;
        }
    }

}

//double functionality slots
void ShaderDialog::changeDoubleComboXvalue ( int newValue ) {
    doubleValueX->setValue ( ( double ) newValue/10 );
}
void ShaderDialog::changeDoubleXSliderValue ( double comboValue ) {
    double fakeValue=10*comboValue;
    doubleSliderX->setValue ( ( int ) fakeValue );
}
void ShaderDialog::changeDoubleXmaximumValue ( double newMaximun ) {
    doubleSliderX->setMaximum ( newMaximun*10 );
}
void ShaderDialog::changeDoubleXminimumValue ( double newMinimum ) {
    doubleSliderX->setMinimum ( newMinimum*10 );
}

void ShaderDialog::changeDoubleComboYvalue ( int newValue ) {
    doubleValueY->setValue ( ( double ) newValue/10 );
}
void ShaderDialog::changeDoubleYSliderValue ( double comboValue ) {
    double fakeValue=10*comboValue;
    doubleSliderY->setValue ( ( int ) fakeValue );
}
void ShaderDialog::changeDoubleYmaximumValue ( double newMaximun ) {
    doubleSliderY->setMaximum ( newMaximun*10 );
}
void ShaderDialog::changeDoubleYminimumValue ( double newMinimum ) {
    doubleSliderY->setMinimum ( newMinimum*10 );
}


void ShaderDialog::changeDoubleComboZvalue ( int newValue ) {
    doubleValueZ->setValue ( ( double ) newValue/10 );
}
void ShaderDialog::changeDoubleZSliderValue ( double comboValue ) {
    double fakeValue=10*comboValue;
    doubleSliderZ->setValue ( ( int ) fakeValue );
}
void ShaderDialog::changeDoubleZmaximumValue ( double newMaximun ) {
    doubleSliderZ->setMaximum ( newMaximun*10 );
}
void ShaderDialog::changeDoubleZminimumValue ( double newMinimum ) {
    doubleSliderZ->setMinimum ( newMinimum*10 );
}

void ShaderDialog::changeDoubleComboWvalue ( int newValue ) {
    doubleValueW->setValue ( ( double ) newValue/10 );
}
void ShaderDialog::changeDoubleWSliderValue ( double comboValue ) {
    double fakeValue=10*comboValue;
    doubleSliderW->setValue ( ( int ) fakeValue );
}
void ShaderDialog::changeDoubleWmaximumValue ( double newMaximun ) {
    doubleSliderW->setMaximum ( newMaximun*10 );
}
void ShaderDialog::changeDoubleWminimumValue ( double newMinimum ) {
    doubleSliderW->setMinimum ( newMinimum*10 );
}

//int functionality slots
void ShaderDialog::changeXmaximum ( int newMaximun ) {
    sliderX->setMaximum ( newMaximun );
}
void ShaderDialog::changeXminimum ( int newMinimum ) {
    sliderX->setMinimum ( newMinimum );
}
void ShaderDialog::changeYmaximum ( int newMaximun ) {
    sliderY->setMaximum ( newMaximun );
}
void ShaderDialog::changeYminimum ( int newMinimum ) {
    sliderY->setMinimum ( newMinimum );
}
void ShaderDialog::changeZmaximum ( int newMaximun ) {
    sliderZ->setMaximum ( newMaximun );
}
void ShaderDialog::changeZminimum ( int newMinimum ) {
    sliderZ->setMinimum ( newMinimum );
}
void ShaderDialog::changeWmaximum ( int newMaximun ) {
    sliderW->setMaximum ( newMaximun );
}
void ShaderDialog::changeWminimum ( int newMinimum ) {
    sliderW->setMinimum ( newMinimum );
}
